namespace netduino.helpers.Imaging {
    /// <summary>
    /// This class generates a bitmap from a text string
    /// </summary>
    public class CharSet : Bitmap
    {
        // We're going old school with a Commodore 64 fonts :) Check out http://kofler.dot.at/c64/#char for more information
        // The hex font data below corresponds to this bitmap: http://kofler.dot.at/c64/charsets/computer.gif
        // You can also make your own using an editor like this: http://www.min.at/prinz/software/pixelfont/
        protected static readonly byte[] FontData = {
            0x3c,0x3c,0xf8,0x7e,0x7c,0x7e,0x7e,0x7e,0x42,0x30,0xc,0x44,0x40,0x7f,0x7c,0x7e,0x7e,0x7e,0x7c,0x7e,0x7e,0x42,0x62,0x41,0x42,0x42,0x7e,0x3c,0xc,0x3c,0x0,0x0,
            0x66,0x24,0x88,0x62,0x62,0x40,0x40,0x62,0x42,0x30,0xc,0x44,0x40,0x49,0x42,0x4e,0x42,0x42,0x44,0x42,0x18,0x42,0x62,0x41,0x42,0x42,0x42,0x30,0x12,0xc,0x18,0x10,
            0x6e,0x24,0x88,0x60,0x62,0x40,0x40,0x60,0x42,0x30,0xc,0x44,0x40,0x49,0x42,0x4e,0x42,0x42,0x44,0x40,0x18,0x42,0x62,0x41,0x42,0x42,0xe,0x30,0x30,0xc,0x3c,0x30,
            0x6e,0xfe,0xfe,0x70,0x72,0x7e,0x7e,0x76,0x7e,0x38,0xe,0x7e,0x70,0x49,0x72,0x4e,0x7e,0x42,0x7e,0x7e,0x1c,0x72,0x62,0x6d,0x3c,0x7e,0x18,0x30,0x7c,0xc,0x7e,0x7f,
            0x60,0xe2,0xe2,0x70,0x72,0x70,0x70,0x72,0x72,0x38,0xe,0x72,0x70,0x69,0x72,0x42,0x70,0x42,0x72,0xe,0x1c,0x72,0x26,0x6d,0x72,0x18,0x70,0x30,0x30,0xc,0x18,0x7f,
            0x62,0xe2,0xe2,0x72,0x72,0x70,0x70,0x72,0x72,0x38,0x4e,0x72,0x70,0x69,0x72,0x42,0x70,0x5e,0x72,0x4e,0x1c,0x72,0x24,0x6d,0x72,0x18,0x42,0x30,0x62,0xc,0x18,0x30,
            0x3c,0xe2,0xfe,0x7e,0x7e,0x7e,0x70,0x7e,0x72,0x38,0x7e,0x72,0x7e,0x69,0x72,0x7e,0x70,0x7e,0x72,0x7e,0x1c,0x7e,0x3c,0x7f,0x72,0x18,0x7e,0x3c,0xfc,0x3c,0x18,0x10,
            0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x18,0x0,
            0x0,0x38,0x66,0x66,0x18,0x62,0x7e,0x6,0xc,0x30,0x0,0x0,0x0,0x0,0x0,0x0,0x7e,0x18,0x7e,0x7c,0x7c,0x7e,0x7e,0x7e,0x3c,0x7e,0x0,0x0,0xe,0x0,0x70,0x7e,
            0x0,0x38,0x66,0x66,0x7e,0x66,0x42,0xc,0x18,0x18,0x66,0x18,0x0,0x0,0x0,0x3,0x42,0x18,0x42,0x44,0x44,0x40,0x42,0x6,0x24,0x42,0x0,0x0,0x18,0x0,0x18,0x46,
            0x0,0x38,0x66,0xff,0x40,0xc,0x20,0x18,0x30,0xc,0x3c,0x18,0x0,0x0,0x0,0x6,0x42,0x18,0x2,0x4,0x44,0x7e,0x40,0x6,0x24,0x42,0x18,0x18,0x30,0x7e,0xc,0x6,
            0x0,0x30,0x0,0x66,0x7e,0x18,0x36,0x0,0x30,0xc,0xff,0x7e,0x0,0x7e,0x0,0xc,0x4e,0x38,0x7e,0x1e,0x44,0xe,0x7e,0xe,0x7e,0x7e,0x0,0x0,0x60,0x0,0x6,0xc,
            0x0,0x30,0x0,0xff,0x6,0x30,0x6a,0x0,0x30,0xc,0x3c,0x18,0x0,0x0,0x0,0x18,0x4e,0x38,0x70,0x6,0x7f,0xe,0x4e,0xe,0x46,0x6,0x0,0x0,0x30,0x7e,0xc,0x18,
            0x0,0x0,0x0,0x66,0x7e,0x66,0x66,0x0,0x18,0x18,0x66,0x18,0x18,0x0,0x18,0x30,0x4e,0x38,0x70,0x46,0x1c,0x4e,0x4e,0xe,0x46,0x46,0x18,0x18,0x18,0x0,0x18,0x0,
            0x0,0x30,0x0,0x66,0x18,0x46,0x7a,0x0,0xc,0x30,0x0,0x0,0x18,0x0,0x18,0x60,0x7e,0x38,0x7e,0x7e,0x1c,0x7e,0x7e,0xe,0x7e,0x7e,0x0,0x18,0xe,0x0,0x70,0x0,
            0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x30,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x30,0x0,0x0,0x0,0x0,
            };

        public CharSet() : base(FontData, 256, 16) {
        }
        /// <summary>
        /// Takes a string and builds a Bitmap object representing the text of the string
        /// </summary>
        /// <param name="text"></param>
        /// <returns>A Bitmap object representing the string</returns>
        public Bitmap StringToBitmap(string text) {
            // Figure out the width in pixels required to build the bitmap matching the text string
            int textWidthInPixels = text.Length * FrameSize;
            var bmpData = new byte[textWidthInPixels];
            int index = 0;
            var upperText = text.ToUpper();
            for (var i = 0; i < text.Length; i++) {
                // Build the target bitmap one character at a time
                CopyBitmapChar(upperText[i], bmpData, index++, text.Length);
            }
            // Create the final bitmap object matching the text string
            var strBmp = new Bitmap(bmpData, textWidthInPixels, FrameSize);
            return strBmp;
        }

        /// <summary>
        /// Maps a character to its corresponding bitmap in the font and copies that bitmap into a target buffer
        /// </summary>
        /// <param name="c">A character to be mapped in the font</param>
        /// <param name="buffer">Target buffer where the character bitmap will be stored</param>
        /// <param name="index">Position of the character in the target buffer</param>
        /// <param name="textLength">Length of the text string being processed</param>
        public void CopyBitmapChar(char c, byte[] buffer, int index, int textLength) {
            // Default character is '@' if the character being passed doesn't exist 
            int x = 0;
            int y = 0;

            // Figure out which line of the font should be used for the character
            // Refer to http://www.ascii-code.com/ ASCII printable characters (character code 32-127)
            if (c >= '@' && c <= '_') {
                x = (c - '@') * FrameSize;
                // 1st line, so no need to set y
            }
            else if (c >= ' ' && c <= '?') {
                x = (c - ' ') * FrameSize;
                y = FrameSize; // 2nd line
            }

            // Grab the bitmap frame matching the character
            var frame = GetFrame(x, y);

            // Copy the character frame into the target bitmap buffer. Build the frame one line at a time
            for (int line = y, frameLine = 0; frameLine < FrameSize; line++, frameLine++) {
                // Figure out where in the target bitmap this frame line should be placed
                var byteIndex = frameLine * textLength + index;
                buffer[byteIndex] = frame[frameLine];
            }
        }
    }
}
